package controller.steam;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import model.Game;
import model.dao.DAOFactory;

import org.apache.http.client.ClientProtocolException;

import util.ER;
import util.Web;
import br.com.robot.util.RobotStatus;
import controller.interfaces.Robot;

public class SteamRobot implements Robot
{
	private int             totalPaginas = 0;
	private ExecutorService executor     = Executors.newFixedThreadPool( 30 );
	private Calendar        dataAtual    = null;
	
	private RobotStatus status = RobotStatus.PARADO;
	
	private StringBuffer sbLogErro = new StringBuffer( );
	
	public SteamRobot( )
	{
		dataAtual = Calendar.getInstance( );
	}
	
	public void iniciar( )
	{
		executor.execute( new Runnable( )
		{
			@Override
			public void run( )
			{
				start( );
			}
		} );
	}

	private void start( )
	{
		status = RobotStatus.RODANDO;
		
		try
		{
			String buscaExprecao = ER.buscaExprecao( Web.get( "http://store.steampowered.com/search/results?sort_order=ASC&page=1" ), 
					 "\\.\\.\\..*?<a href.*?>(.*?)</" );

			totalPaginas = Integer.parseInt( buscaExprecao );
			
			buscaProximo( 1 );
			
			executor.shutdown( );
			
			verificadorDoRobo( );
		}
		catch( Exception e )
		{
			logaErro( e );
			e.printStackTrace( );
		}
	}
	
	private void verificadorDoRobo( )
	{
		try
		{
			new Thread( new Runnable( )
			{
				@Override
				public void run( )
				{
					while( !executor.isTerminated( ) ) { }
					
					status = RobotStatus.PARADO;
				}
			} ).start( );
		}
		catch( Exception e )
		{
			logaErro( e );
			e.printStackTrace( );
			
			status = RobotStatus.PARADO;
		}
	}

	private void buscaProximo( final int nPag ) throws ClientProtocolException, IOException
	{
		executor.execute(  new Runnable( )
		{
			public void run( )
			{
				try
				{
					buscaExprecao( Web.get( "http://store.steampowered.com/search/results?sort_order=ASC&page=" + nPag ),
								   "class=\"col search_name ellipsis\">.*?<h4>(.*?)</",
					               "<div class=\"col search_price.*?\">(.*?)</div>",
					               "<div class=\"col search_metascore\">(.*?)</",
					               "<div class=\"col search_released\">(.*?)</",
					               "<a href=\"(.*?)\" class=\"search_result_row.*? >", nPag );
				} 
				catch( FileNotFoundException e )
				{
					logaErro( e );
					e.printStackTrace( );
				} 
				catch( ClientProtocolException e ) 
				{
					logaErro( e );
					e.printStackTrace( );
				} 
				catch( IOException e ) 
				{
					logaErro( e );
					e.printStackTrace( );
				}
				catch( Exception e ) 
				{
					logaErro( e );
					e.printStackTrace( );
				}
			}
		} );
		
		if( nPag < totalPaginas )
			buscaProximo( nPag + 1 ); 
	}
	
	private void buscaExprecao( String strTexto, String expNome, String expPreco, String expMeta1score, String expLancamento, String expUrl, int nPag ) throws Exception
	{
		List<String[]> find = ER.findAll( strTexto, expPreco, expMeta1score, expLancamento, expNome );
		
		String         bloco = ER.buscaExprecao( strTexto, "<div></div>(.*?)class=\"search_pagination\"" );
		List<String[]> urls  = ER.findAll      ( bloco,    expUrl                                        );
		
		List<Game> games = new ArrayList<Game>( );
		Game       game;
		
		for( String[] aItens : find )
		{
			game = new Game( );
			
			if( aItens[0].contains( "<strike>" ) )
			{
				game.setPrecoAtu    ( Web.filter( ER.buscaExprecao( aItens[0], ".*?</span><br>(.*)$"          ) ) );
				game.setPrecoOrignal( Web.filter( ER.buscaExprecao( aItens[0], ".*?<strike>(.*?)</strike>.*$" ) ) );
			}
			else
			{
				game.setPrecoAtu(Web.filter( aItens[0] ));
			}
			
			game.setMetaScore ( aItens[1] );
			game.setLancamento( aItens[2] );
			game.setNome      ( aItens[3] );
			
			games.add( game );
		}
		
		for( int i = 0; i < games.size( ); i++ )
		{
			games.get( i ).setUrl       ( urls.get( i )[0] );
			games.get( i ).setDataVisita( dataAtual        );
		}
		
		if( DAOFactory.infGameDao( ).save( games ) == 1 )
		{
			logaMenssagem( String.format( "INFO: Pagina %s, registros inseridos %d", nPag, games.size( ) ) );
		}
		else
		{
			logaMenssagem( "ERROR: Erro ao inserir" );
		}
	}

	@Override
	public void parar( )
	{
		status = RobotStatus.PARADO;
		executor.shutdownNow( );
	}

	@Override
	public RobotStatus verificarStatus( )
	{
		return status;
	}

	@Override
	public StringBuffer infLog( )
	{
		return sbLogErro;
	}
	
	private void logaErro( Exception e )
	{
		StackTraceElement[] stackTrace = e.getStackTrace( );
		
		sbLogErro.append( e.getMessage( ) + "<br />\r\n" );
		
		for( StackTraceElement stackTraceElement : stackTrace ) 
		{
			sbLogErro.append( stackTraceElement.getFileName( )   );
			sbLogErro.append( stackTraceElement.getMethodName( ) );
			sbLogErro.append( stackTraceElement.getLineNumber( ) );
			
			sbLogErro.append( "<br />\r\n" );
		}
	}
	
	private void logaMenssagem( String menssagem )
	{
		sbLogErro.append( menssagem + "<br />\r\n" );
	}
}